package com.csthink.common.infrastructure.util;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.Map;

/**
 * @author <a href="mailto:security.2009@live.cn">Mars</a>
 * @since 2023-09-12
 */

@Slf4j
@Component
public class JwtUtils {

    @Value("${jwt.secretKey}")
    private String secretKey;

    @Value("${jwt.token.timeout:}")
    private int jwtTokenTimeout;

    private final static long TTL = 60 * 60 * 1000;

    /**
     * build external JWT
     */
    public String createJWT(String issuer, String audience, Map<String, Object> customClaims) {

        Date issueAt = new Date();
        Date expiresAt = new Date(issueAt.getTime() + TTL * jwtTokenTimeout);

//        Calendar c = Calendar.getInstance();
//        c.setTime(new Date());
//        c.add(Calendar.SECOND, Math.toIntExact(TTL));
//        Date expiresAt = c.getTime();

        JwtBuilder jwtBuilder = Jwts.builder()
                .setIssuer(issuer)
                .setAudience(audience)
                .setIssuedAt(issueAt)
                .setExpiration(expiresAt)
                .signWith(SignatureAlgorithm.HS256, secretKey);

        if (MapUtils.isNotEmpty(customClaims)) {
            jwtBuilder.addClaims(customClaims);
        }

        if (log.isDebugEnabled()) {
            log.debug("jwt token issue date and expire date :{},{}", issueAt, expiresAt);
        }

        return jwtBuilder.compact();
    }

    public Claims parseJwt(String token) {
        if (StringUtils.isBlank(token)) {
            return null;
        }

        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), SignatureAlgorithm.HS256.getJcaName());

        Claims claims = null;

        // 解析失败了会抛出异常，所以我们要捕捉一下。token过期、token非法都会导致解析失败
        try {
            claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (JwtException e) {
            log.error("token解析失败", e);

            throw e;
        }

        return claims;
    }


}
